﻿using EnterpriseDT.Net.Ftp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FTPC {
    class UpLoadFileTools {
        private String serverIp;
        private String username;
        private String password;
        private String port;
        private FTPClient ftp;
        private long transferNotifyInterval;


        public long TransferNotifyInterval {
            get { return transferNotifyInterval; }
            set { transferNotifyInterval = value; }
        }

        public UpLoadFileTools(string sip, string port, string uname, string pwd) {
            this.serverIp = sip;
            this.username = uname;
            this.password = pwd;
            this.port = port;
            ftp = new FTPClient ( );
            ftp.BytesTransferred += new BytesTransferredHandler (ftp_BytesTransferred);
            ftp.TransferCompleteEx += new TransferHandler (ftp_TransferCompleteEx);
            MyConnect ( );
        }

        void ftp_TransferCompleteEx(object sender, TransferEventArgs e) {
            TransferComplete.Invoke (sender, e);
        }



        public event BytesTransferredHandler BytesTransferred;
        public event TransferHandler TransferComplete;

        void ftp_BytesTransferred(object sender, BytesTransferredEventArgs e) {
            BytesTransferred.Invoke (sender, e);
        }

        public bool MyUpload(UpLoadJob job) {
            bool res = true;
            String remotePath = "/";
            this.MyConnect ( );
            try {
                ftp.ChDir (remotePath);
            } catch (Exception ex) {
                MessageBox.Show (ex.Message, "ULFT-MyUpload1");
                res = false;
            }
            try {
                FileInfo fi = new FileInfo (job.localpath);

                ftp.TransferNotifyInterval = (long)((double)fi.Length / (double)100);
                job.setState (JobState.UPLOADING);
                if (ftp.Exists (job.filename)) {
                    ftp.Resume ( );
                }
                ftp.Put (job.localpath, job.filename);
                string savePath = makeVerifyFile (fi);
                ftp.Put (savePath, fi.Name + ".fileinfo");
                File.Delete (savePath);
            } catch (Exception ex) {
                MessageBox.Show (ex.Message, "ULFT-MyUpload2");
                res = false;
            }
            return res;
        }
        public void ReName(String upfilename, String newfilename) {
            try {
                ftp.Rename (upfilename, newfilename);
            } catch (Exception ex) {
                MessageBox.Show (ex.Message, "ULFT-ReName");
            }
        }

        public bool ExistsRemoteFile(string remoteFileName) {
            MyConnect ( );
            return ftp.Exists (remoteFileName);
        }

        public long getExistsRemoteFileSize(string remoteFileName) {
            try {
                MyConnect ( );
                return ftp.Size (remoteFileName);
            } catch (Exception ex) {
                MessageBox.Show (ex.Message, "ULFT-getExistRemoteFileSize");
                return 0;
            }
        }

        public void disConnect() {
            if (ftp.IsConnected) {
                ftp.QuitImmediately ( );
            }
        }

        public void MyConnect() {
            if (!ftp.IsConnected) {
                try {
                    ftp.RemoteHost = serverIp;
                    ftp.ControlEncoding = Encoding.UTF8;
                    ftp.ControlPort = Convert.ToInt16 (this.port);
                    ftp.Connect ( );
                } catch (Exception ex) {
                    MessageBox.Show (ex.Message, "ULFT-MyConnect1");
                }

                try {
                    ftp.Quote ("OPTS UTF8 ON", null);
                    ftp.Login (username, password);
                } catch (Exception ex) {
                    MessageBox.Show (ex.Message, "ULFT-MyConnect2");
                }

                ftp.ConnectMode = FTPConnectMode.PASV;
                ftp.TransferType = FTPTransferType.BINARY;
            }
        }

        public string makeVerifyFile(FileInfo sourceFile) {
            string saveDisk = "";
            DriveInfo[] disk = DriveInfo.GetDrives();
            foreach (DriveInfo di in disk) {
                if ("C:\\" != di.Name.ToUpper()) {
                    try {
                        if (!Directory.Exists (di.Name + "adccFTPClienttemp")) {
                            Directory.CreateDirectory (di.Name + "adccFTPClienttemp");
                            File.SetAttributes (di.Name + "adccFTPClienttemp", FileAttributes.Hidden);
                        }
                        saveDisk = di.Name + "adccFTPClienttemp";
                        
                        break;
                    } catch (Exception e) {}
                }
            }
            if ("" == saveDisk) {
                saveDisk = System.Environment.CurrentDirectory;
            }
            string savePath =  saveDisk + "\\" + sourceFile.Name + ".fileinfo";
            //创建文件流
            FileStream myfs = new FileStream (savePath, FileMode.Append);
            //创建写入器
            StreamWriter mySw = new StreamWriter (myfs);
            //写入文件
            mySw.WriteLine (GetFileHash (sourceFile.FullName));
            //mySw.WriteLine(sourceFile.Length);
            //关闭写入器
            mySw.Close ( );
            //关闭文件流
            myfs.Close ( );

            return savePath;
        }

        public static string GetFileHash(string argFilePath) {
            using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider ( ))
            using (FileStream fs = new FileStream (argFilePath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                return BitConverter.ToString (md5.ComputeHash (fs)).Replace ("-", "");
            }
        }

        public void cleanFileinfo(string filename) {
            if (filename == null) {
                DirectoryInfo di = new DirectoryInfo (System.Environment.CurrentDirectory);
                var fis = di.GetFiles ( ).Where (file => file.Name.IndexOf (".fileinfo") > -1);
                foreach (FileInfo fi in fis) {
                    fi.Delete ( );
                }
            } else {
                string destPath = System.Environment.CurrentDirectory + "\\" + filename + ".fileinfo";
                FileInfo fi = new FileInfo (destPath);
                fi.Delete ( );
            }
        }
    }

}
